#include <p24FJ256GA106.h>
#include <stdio.h>


/*====================================================================
InitADC1() is used to configure A/D to convert channel 5 on Timer
 event. It generates interrupt on every 16 sample/convert sequence. 
 ADC clock is configured at 125Khz 
====================================================================*/
void InitADC1(void)
{
  // AD1PCFGH/AD1PCFGL: Port Configuration Register
  AD1PCFGL = 0xFFFF; // All pins digtal

  // Configure pins as input
  TRISBbits.TRISB2 = 1; //nodig?
  TRISBbits.TRISB3 = 1; //nodig?

  AD1PCFGLbits.PCFG2	= 0;		//AN2 ADC pin
  AD1PCFGLbits.PCFG3	= 0;		//AN3 ADC pin  

    //AD1CON1 Register
    // Data Output Format: Signed Fraction (Q15 format)
    //AD1CON1bits.FORM = 3;		
  // Sample Clock Source: Timer 3 starts conversion
  AD1CON1bits.SSRC = 2;

  //AD1CSSH/AD1CSSL: A/D Input Scan Selection Register
  // Channel Scan is disabled, default state
  AD1CSSL = 0x0000;			

  //AD1CON2 Register
  // Generate interrupt every 16 sample/conversion
  AD1CON2bits.SMPI = 15;		
  // Buffer configured as one 16-word buffers
  AD1CON2bits.BUFM = 0;		

  //AD1CON3 Register        
  // ADC Clock is derived from Systems Clock
  AD1CON3bits.ADRC = 0;		
	
  // ADC Conversion Clock Tad=Tcy*(ADCS+1)=(1/8M)*2*32 = 8us (125Khz)
  // ADC Conversion Time for 10-bit Tc=12*Tab = 96us		
  AD1CON3bits.ADCS = 31;		
												

  //AD1CHS0: A/D Input Select Register
  // MUXA +ve input selection (AIN2) for CH0
  AD1CHSbits.CH0SA = 3;		
  // MUXA -ve input selection (Vref-) for CH0
  AD1CHSbits.CH0NA = 0;		
		
  // ADC Sample Control: Sampling begins immediately after conversion
  AD1CON1bits.ASAM = 1;
  
  IFS0bits.AD1IF = 0;			// Clear the A/D interrupt flag bit
  IEC0bits.AD1IE = 1;			// Enable A/D interrupt 
  AD1CON1bits.ADON = 1;		// Turn on the A/D converter	
}

unsigned int ADCValue, count;
int *ADC16Ptr;

unsigned int ADC_SB;
unsigned int ADC_BB;
unsigned int ADC_Stuur;
int SetSB_PR = -1;

// Tijdens het programmeren wordt het stuursignaal genegeerd,
// Bij remmen, negeer dan ook het stuursignaal. 
// De kleppen moeten dan volledig uit
#define PR_MODE		PORTBbits.RB8


void _ISR _ADC1Interrupt(void)
{
  ADCValue = 0; // clear value
  ADC16Ptr = &ADC1BUF0; // initialize ADC1BUF pointer

  for (count = 0; count < 16; count++) // average the 16 ADC value
  {
	ADCValue = ADCValue + *ADC16Ptr++;
  }
  ADCValue = ADCValue >> 4;

  switch(AD1CHSbits.CH0SA) {
    case 2 : 
	  // Switch analog input
	  AD1CHSbits.CH0SA = 3;
	  ADC_SB =  ADCValue;

	  // Welke waarde moet UpdateSB gebruiken om het stuur signaal te bepalen.
	  if(PR_MODE==1 && SetSB_PR >= 0)
	  { // Programmeer bordje is aangesloten en heeft SetSB_PR van waarde veranderd
		UpdateSB(SetSB_PR);
	  }
 	  else 
	  { // Standaard mode
		UpdateSB(ADC_Stuur);
	  }
    break;
    case 3 : 
	  // Switch analog input
	  AD1CHSbits.CH0SA = 2;
	  ADC_Stuur =  ADCValue;
	  //putsU1(" 3: ");
	  //putU1Dec(ADCValue);
    break;
	default :
	  AD1CHSbits.CH0SA = 3;
	break;
  }


  IFS0bits.AD1IF = 0; // clear ADC interrupt flag
}



unsigned int GetADC_SB(int range)
{
  switch(range)
  {
    // range 0..100
	case 100 :
	  return (ADC_SB > 0 ? (ADC_SB+1)/10.24 : 0);
    break;
	// range 0..511
    case 511 :
  	  return (511-(ADC_SB > 0 ? ((ADC_SB)/2) : 0) );
    break;
	// range 0..1023
	default:
    case 1023 :
      return ADC_SB;
    break;
  }
}

unsigned int GetADC_BB(void)
{
  return (ADC_BB+1)/10.24;
}

void SetSB_PR_Mode(int value)
{
  SetSB_PR = (511-(value > 0 ? (value*5.12)-1 : 0));
}

void ClearVarsPR_Mode(void) 
{
  SetSB_PR = -1;
}
